<template>
  <div class="eye-page">
    <header class="controls">
      <div class="left">
        <label>测试距离（米）：
          <select v-model.number="distance">
            <option v-for="d in distances" :key="d" :value="d">{{ d }}m</option>
          </select>
        </label>
        <button @click="startTest" v-if="!running" class="btn btn-start">开始测试</button>
        <button @click="restart" v-else class="btn btn-reset">重置</button>
        <button @click="testComplete" class="btn btn-complete">测试完成</button>
      </div>
      <div class="right">
        <div class="instructions">
          - 两人配合：一人出题（点击本页面），一人看屏幕回答E标识方向。
          - 按 <strong>空格</strong> 或 <strong>点击屏幕</strong> 切换下一档，E 会由大渐渐变小并随机朝向。
        </div>
      </div>
    </header>

    <main class="stage" @click="next">
      <div class="optotype-area">
        <div
          v-if="running"
          class="optotype"
          :style="optotypeStyle"
          :class="{anim: anim}">
          E
        </div>
        <div v-else class="placeholder">点击“开始测试”以开始</div>
      </div>

      <aside class="status">
        <div><strong>当前档位：</strong> {{ currentIndexLabel }}</div>
        <div><strong>对应视力：</strong> {{ currentAcuityLabel }}</div>
        <div><strong>方向：</strong> {{ orientationText }}</div>
        <div><strong>当前试次：</strong> {{ trialLabel }}</div>
        <div v-if="finished" class="finished">测试完成 — 请记录被测视力</div>
        <hr />
        <div class="legend">
          <div v-for="(label, i) in acuityLabels" :key="i">档 {{ i+1 }} ：{{ label }}</div>
        </div>
        <div v-if="result" class="result-box">
          <div><strong>测试结果（可复制保存）：</strong></div>
          <textarea readonly class="result-text">{{ result }}</textarea>
          <div style="margin-top:6px; display:flex; gap:8px">
            <button class="copy-btn" @click.stop.prevent="copyResult">复制结果</button>
            <button @click.stop.prevent="clearResult">清除</button>
          </div>
        </div>
      </aside>
    </main>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue'

const distances = [1,2,3,4,5,6,8,10]
const distance = ref(5)

// 精确化的视力档位（从大到小）：每一档对应的十进制视力值
// 选取 8 档：0.1 -> 1.0（从差到好），并为 5m 参考距离定义基准像素尺寸。
// 基准尺寸以最小档（1.0）为 36px，按 1/视力 比例放大：size = 36 * (1 / acuity)
// 更细化的视力档位（从差到好），包含 0.12、0.15、0.25 等常见档位
const acuityLabels = ['0.1','0.12','0.15','0.2','0.25','0.3','0.4','0.5','0.6','0.8','1.0']
// 基准像素尺寸采用 36px 为 1.0 视力，按 36 / 视力 计算
const baseSizes = [360, 300, 240, 180, 144, 120, 90, 72, 60, 45, 36]

const running = ref(false)
const index = ref(0) // current level index (0..n-1)
const orientation = ref(0) // degrees
const anim = ref(false)
const finished = ref(false)
const result = ref('') // 页面内显示的结果文本，可复制保存
// 每档的试次数（每档出现多少次随机 E）
const trialsPerLevel = 3
const trial = ref(0) // current trial index within the level (0..trialsPerLevel-1)

const currentSize = computed(() => {
  const refSize = baseSizes[index.value] || 36
  // scale by distance relative to 5m: further distance -> larger optotype to compensate
  return Math.round(refSize * (distance.value / 5))
})

const optotypeStyle = computed(() => ({
  width: currentSize.value + 'px',
  height: currentSize.value + 'px',
  fontSize: Math.round(currentSize.value * 0.9) + 'px',
  transform: `rotate(${orientation.value}deg) scale(1)`
}))

const currentIndexLabel = computed(() => index.value + 1 + '/' + baseSizes.length)
const currentAcuityLabel = computed(() => acuityLabels[index.value] || '-')
const trialLabel = computed(() => (trial.value + 1) + '/' + trialsPerLevel)

function randomOrientation() {
  // choose from 0,90,180,270
  const opts = [0, 90, 180, 270]
  orientation.value = opts[Math.floor(Math.random() * opts.length)]
}


function startTest() {
  running.value = true
  finished.value = false
  index.value = 0
  trial.value = 0
  randomOrientation()
  // trigger entry animation
  anim.value = true
  setTimeout(() => (anim.value = false), 350)
}

function next() {
  if (!running.value || finished.value) return
  // 先推进本档的试次
  if (trial.value < trialsPerLevel - 1) {
    trial.value++
    randomOrientation()
    anim.value = true
    setTimeout(() => (anim.value = false), 350)
    return
  }

  // 本档的三次已完成，移动到下一档
  if (index.value < baseSizes.length - 1) {
    index.value++
    trial.value = 0
    randomOrientation()
    anim.value = true
    setTimeout(() => (anim.value = false), 350)
  } else {
    finished.value = true
    running.value = false
  }
}

function restart() {
  running.value = false
  finished.value = false
  index.value = 0
  trial.value = 0
}

// 视力到近视度数的估算映射（依据用户提供的对应表，近似仅供参考）
const diopterMap = {
  '0.1': '近视度数约 650 度',
  '0.12': '近视度数约 500~600 度',
  '0.15': '近视度数约 500 度',
  '0.2': '近视度数约 450 度',
  '0.25': '近视度数约 400 度',
  '0.3': '近视度数约 300~350 度',
  '0.4': '近视度数约 250 度',
  '0.5': '近视度数约 200 度',
  '0.6': '近视度数约 150 度',
  '0.8': '近视度数约 100 度',
  '1.0': '正常视力'
}

function testComplete() {
  // 使用当前档位的视力标签来估算度数，并在页面内展示结果，方便复制保存
  const acuity = currentAcuityLabel.value
  const estimate = diopterMap[acuity] || '无法估算（档位未匹配）'

  const lines = Object.keys(diopterMap).map(k => `${k} → ${diopterMap[k]}`)
  const message = `当前视力档位：${acuity}\n估算：${estimate}\n\n参考映射：\n${lines.join('\n')}`

  result.value = message
  // 标记测试完成状态
  finished.value = true
  running.value = false
}

async function copyResult() {
  if (!result.value) return
  try {
    await navigator.clipboard.writeText(result.value)
    // 简单的用户提示，使用浏览器原生 alert 作为最小反馈
    window.alert('已复制结果到剪贴板')
  } catch (err) {
    // 备用：创建 textarea 复制
    const ta = document.createElement('textarea')
    ta.value = result.value
    document.body.appendChild(ta)
    ta.select()
    try { document.execCommand('copy') } catch (e) {}
    document.body.removeChild(ta)
    window.alert('复制已尝试，若未成功请手动复制结果框内容')
  }
}

function clearResult() {
  result.value = ''
}

function onKey(e) {
  if (e.code === 'Space') {
    e.preventDefault()
    if (!running.value) startTest()
    else next()
  }
}

onMounted(() => {
  window.addEventListener('keydown', onKey)
})
onBeforeUnmount(() => {
  window.removeEventListener('keydown', onKey)
})

const orientationText = computed(() => {
  const map = {0: '向右', 90: '向下', 180: '向左', 270: '向上'}
  return map[orientation.value] || orientation.value + '°'
})

watch(distance, () => {
  // when distance changes, we keep current index but size will recalc automatically
})
</script>

<style scoped>
.eye-page { display:flex; flex-direction:column; height:100%; padding:18px; box-sizing:border-box }
.controls { display:flex; justify-content:space-between; align-items:center; margin-bottom:12px }
.controls label { margin-right:12px }
.stage { display:flex; gap:20px; flex:1; align-items:center }
.optotype-area { flex:1; display:flex; align-items:center; justify-content:center; height:60vh; border-radius:8px; background: #fafafa; cursor:pointer }
.optotype { display:flex; align-items:center; justify-content:center; border-radius:4px; transition:transform 0.35s ease, font-size 0.35s ease; user-select:none }
.optotype.anim { transform: scale(1.45) }
.optotype, .placeholder { font-weight:700; color:#111 }
.placeholder { color:#888 }
.status { width:220px; font-size:14px }
.legend { margin-top:10px; font-size:13px; color:#444 }
.finished { margin-top:10px; color:green; font-weight:600 }

.result-box { margin-top:12px; background:#fff; border:1px solid #e6e6e6; padding:10px; border-radius:6px }
.result-text { width:100%; min-height:78px; resize:vertical; padding:8px; box-sizing:border-box; font-size:13px }
.copy-btn { background:#007bff; color:#fff; border:none; padding:6px 10px; border-radius:4px; cursor:pointer }
.copy-btn:hover { opacity:0.95 }

/* Buttons in the control area: larger, clearer and touch-friendly */
.controls .left .btn { margin-left:8px; padding:8px 14px; border-radius:8px; border:1px solid #d0d7e9; background:#ffffff; cursor:pointer; font-weight:700; box-shadow:0 1px 0 rgba(0,0,0,0.03); transition:all .15s ease }
.controls .left .btn:hover { transform:translateY(-1px); box-shadow:0 4px 10px rgba(16,24,40,0.06) }
.controls .left .btn:active { transform:translateY(0) }
.controls .left .btn:focus { outline:2px solid rgba(59,130,246,0.25); outline-offset:2px }
.controls .left .btn-start { background: linear-gradient(180deg,#3b82f6,#2563eb); color:#fff; border-color:transparent }
.controls .left .btn-reset { background:#fff; color:#111; border-color:#d1d5db }
.controls .left .btn-complete { background:#10b981; color:#fff; border-color:transparent }

/* Make buttons slightly larger on small screens */
@media (max-width:640px) {
  .controls .left .btn { padding:10px 16px; font-size:15px }
}

/* center the E visually */
.optotype { display:flex; align-items:center; justify-content:center; background:transparent }

/* Make the letter E use a blocky font look */
.optotype { font-family: 'Arial', 'Helvetica', sans-serif }
</style>
